<template>
  <div class="app-container category-page">
    <el-row :gutter="4">
      <el-col :span="6">
        <el-card v-loading="treeLoading" class="card-h-100">
          <div class="pb-10">
            <el-input v-model.trim="filterText" size="mini" placeholder="输入关键字进行过滤" />
          </div>
          <div class="tree-warp">
            <el-tree
              ref="tree"
              class="filter-tree"
              node-key="id"
              :data="data"
              :props="treeprops"
              :default-expand-all="false"
              :default-expanded-keys="['']"
              :filter-node-method="filterNode"
              :expand-on-click-node="false"
              :render-content="renderContent"
            />
          </div>
        </el-card>
      </el-col>
      <el-col :span="18">
        <el-card v-loading="saveLoading" class="card-h-100">
          <el-form v-if="formDataReady" ref="myform" :rules="rules" :model="formItem" label-width="100px" size="mini" class="attr-form">
            <el-form-item v-if="formItem.parent" label="上级分类" prop="parent">
              <span>{{ formItem.parent }}</span>
            </el-form-item>
            <el-form-item label="分类名称" prop="name">
              <el-input v-model.trim="formItem.name" placeholder="请输入分类名称" />
            </el-form-item>
            <el-form-item label="分类编码" prop="code">
              <el-input v-model.trim="formItem.code" placeholder="请输入分类编码" />
            </el-form-item>
            <el-form-item v-for="(attr, index) in formItem.attrs" :key="attr._dirty" :label="attr.name">
              <dynamic-attr-form v-model="formItem.attrs[index]" @delete="onRemoveAttr(formItem.attrs[index])" />
            </el-form-item>
            <el-form-item>
              <el-button v-show="formItem.parentId" type="text" icon="el-icon-plus" @click="onAddAttr">添加属性</el-button>
              <el-button type="primary" style="margin-right: 20px;" @click="onSave">保存</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import { options as tree, detail, update, create, remove } from '@neu/cmdb-ui/api/category'
import { deepClone, createUniqueString } from '@neu/biz-core/utils'
import ValidatorSchema from 'async-validator'
import DynamicAttrForm from '@neu/cmdb-ui/components/DynamicAttrForm'

// 定义一个表单原始项
const formItem = {
  id: '',
  name: '',
  code: '',
  attrs: [],
  parent: '',
  parentId: '',
  parentName: ''
}

// 表单验证规则
const rules = {
  name: [{
    required: true,
    message: '分类名称必填项',
    trigger: 'blur'
  }],
  code: [{
    required: true,
    message: '分类编码必填项',
    trigger: 'blur'
  }]
}

export default {
  name: 'CategoryTreePage',
  components: {
    DynamicAttrForm
  },
  data() {
    return {
      treeLoading: false,
      saveLoading: false,
      filterText: '',
      /** 资产分类树 */
      data: [],
      treeprops: {
        label: 'label',
        children: 'children'
      },
      formItem: {
        ...formItem
      },
      formDataReady: true,
      rules: { ...rules },
      descriptor: {}
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  created() {
    this.$store.dispatch('cmdb/loadDatatypes')
    this.$store.dispatch('cmdb/loadRelationtypes')
    this.tree()
  },
  methods: {
    // 渲染分类树节点项，支持按钮操作
    renderContent(h, { node, data }) {
      if (node.level === 2) {
        return (
          <span class='custom-tree-node'>
            <span>{node.label}</span>
            <span>
              <el-button size='mini' type='text' title='添加子分类' on-click={ () => this.onAdd(node, data) } icon='el-icon-plus' />
              <el-button size='mini' type='text' title='编辑分类' on-click={ () => this.onEdit(node, data) } icon='el-icon-edit' />
              <el-button size='mini' type='text' title='删除子分类' on-click={ () => this.onRemove(node, data) } icon='el-icon-delete' />
            </span>
          </span>
        )
      } else if (node.level === 3) {
        return (
          <span class='custom-tree-node'>
            <span>{node.label}</span>
            <span>
              <el-button size='mini' type='text' title='编辑分类' on-click={ () => this.onEdit(node, data) } icon='el-icon-edit' />
              <el-button size='mini' type='text' title='删除子分类' on-click={ () => this.onRemove(node, data) } icon='el-icon-delete' />
            </span>
          </span>
        )
      } else {
        return (
          <span class='custom-tree-node'>
            <span>{node.label}</span>
            <span>
              <el-button size='mini' type='text' title='添加子分类' on-click={ () => this.onAdd(node, data) } icon='el-icon-plus' />
            </span>
          </span>
        )
      }
    },
    // 加载分类树
    tree() {
      this.treeLoading = true
      tree().then(response => {
        // 添加一个虚拟顶点
        const data = [{
          id: '',
          label: '所有分类',
          value: '',
          children: response.data
        }]
        this.data = data
        this.treeLoading = false
      })
    },
    // 过滤分类树
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    // 编辑一个分类
    onEdit(node, data) {
      this.saveLoading = true
      this.formDataReady = false
      detail(data.id).then(response => {
        // 加一个临时_dirty，方便前端维护，提交时忽略_dirty
        const attrs = response.data.attrs.map(it => { it._dirty = createUniqueString(); it._error = { name: false, dtype: false, field: false }; return it })
        this.formItem = {
          id: response.data._id,
          name: response.data.name,
          code: response.data.code,
          attrs: attrs
        }
        if (node.level === 3) {
          this.formItem.parent = node.parent.data.value
          this.formItem.parentId = node.parent.data.id
          this.formItem.parentName = node.parent.data.label
        }

        this.saveLoading = false
        this.formDataReady = true
      })
    },
    // 删除一个分类
    onRemove(node, data) {
      this.$confirm('确定要删除分类吗', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        remove(data.id).then(response => {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.$refs.tree.remove(node)
        })
      })
    },
    // 添加一个子分类
    onAdd(parentNode, parentData) {
      this.formDataReady = false
      const formData = {
        ...formItem
      }
      if (parentNode.level === 2) {
        formData.parent = parentData.value
        formData.parentId = parentData.id
        formData.parentName = parentData.label
      }
      this.formItem = { ...formData }
      this.formDataReady = true
    },
    // 添加一个属性
    onAddAttr() {
      if (!this.formItem.attrs.some(a => a.field === '')) {
        this.formItem.attrs.push({
          _dirty: createUniqueString(),
          _error: { name: false, dtype: false, field: false },
          _inherit: false,
          name: '',
          field: '',
          dtype: '',
          len: 255,
          dvalue: '',
          notnullable: false,
          enums: [],
          datasource: {}
        })
      }
    },
    // 移除一个属性
    onRemoveAttr(attr) {
      const idx = this.formItem.attrs.findIndex(a => a.field === attr.field)
      this.formItem.attrs.splice(idx, 1)
    },
    // 保存分类
    onSave() {
      const that = this
      this.$refs.myform.validate((valid) => {
        if (!valid) return

        this.descriptor['attrs'] = {
          type: 'array',
          fields: {}
        }
        this.formItem.attrs.forEach((attr, idx) => {
          attr._error = { name: false, dtype: false, field: false }
          const attrRule = {
            type: 'object',
            required: true,
            fields: {
              name: [{
                type: 'string',
                required: true
              }, {
                validator: (rule, value, callback) => {
                  let count = 0
                  this.formItem.attrs.forEach(it => {
                    if (value && it.name === value) count++
                  })
                  if (count > 1) {
                    callback('属性名不能重复')
                  } else {
                    callback()
                  }
                }
              }],
              field: [{
                type: 'string',
                required: true
              }, {
                validator: (rule, value, callback) => {
                  let count = 0
                  this.formItem.attrs.forEach(it => {
                    if (value && it.field === value) count++
                  })
                  if (count > 1) {
                    callback('属性标识不能重复')
                  } else {
                    if (value === 'code' || value === 'name') {
                      callback('code和name是保留关键字')
                    } else {
                      callback()
                    }
                  }
                }
              }],
              dtype: { type: 'string', required: true }
            }
          }
          this.descriptor['attrs'].fields[idx] = attrRule
        })
        var validator = new ValidatorSchema(this.descriptor)
        validator.validate(this.formItem, (errors, fields) => {
          if (errors) {
            errors.forEach(error => {
              const parts = error.field.split('.')
              const attrIndex = parts[1]
              const fieldName = parts[2]
              that.formItem.attrs[attrIndex]._error[fieldName] = true
            })
            return
          }

          this.saveLoading = true
          const { name, parent, code, attrs } = this.formItem
          const mAttrs = deepClone(attrs).map(it => { delete it._dirty; delete it._error; delete it._inherit; return it })

          if (this.formItem.id) {
            update(this.formItem.id, { name, parent, code, attrs: mAttrs }).then(response => {
              const { _id, code, name } = response.data
              const node = this.$refs.tree.getNode(_id)
              node.data.label = name
              node.data.value = code
              this.saveLoading = false
              this.$message({
                type: 'success',
                message: '保存成功!'
              })
            })
          } else {
            create({ name, parent, code, attrs: mAttrs }).then(response => {
              const { _id, code, name } = response.data
              this.$refs.tree.append({
                id: _id,
                label: name,
                value: code
              }, this.formItem.parentId)
              this.saveLoading = false
              this.$message({
                type: 'success',
                message: '保存成功!'
              })
            })
          }
        })
      })
    }
  }
}
</script>
<style lang="scss">

.category-page {
  .tree-warp{
    overflow: auto;
    height:calc(100vh - 150px)
  }

  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }

  .attr-form {
    .dynamic-attr {
      .el-form-item__content {
        display: flex;
        .el-input,
        .el-select {
          margin-right: 20px;
          min-width: 100px;
        }

        .el-checkbox {
          margin-right: 20px;
        }
      }
    }
  }

  .validate-error {
    input {
      border-color: #ff4949;
    }
  }
}
</style>
